package com.zw.re.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;

/**
 *
 * <p><b>spring-data-redis的序列化类有下面这几个: </b>
 * <ul>
 * <li>GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化</li>
 * <li>Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的</li>
 * <li>JacksonJsonRedisSerializer: 序列化object对象为json字符串</li>
 * <li>JdkSerializationRedisSerializer: 序列化java对象</li>
 * <li>StringRedisSerializer: 简单的字符串序列化</li>
 * </ul>
 * <p>一般情况下 如果key-value都是string的话，使用StringRedisSerializer就可以了，
 * <p>如果需要保存对象为json的话推荐使用JacksonJsonRedisSerializer，
 *    它不仅可以将对象序列化，还可以将对象转换为json字符串并保存到redis中，
 *    但需要和jackson配合一起使用。
 *
 * Created by zwz
 * date 2016/12/1
 * project com.htsec.tool.redis.service
 */
@Service
public class SerializerUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 序列化 key  （K）
     * @param key
     * @return
     */
    public byte[] serializerKey(Object key) {
        Assert.notNull(key, "non null key required");
        if (redisTemplate.getKeySerializer() == null && key instanceof byte[]) {
            return (byte[]) key;
        }
        return redisTemplate.getKeySerializer().serialize(key);
    }

    /**
     * 序列化 hash 键   （HK）
     * @param hashKey
     * @return
     */
    public byte[] serializerHashKey(Object hashKey) {
        Assert.notNull(hashKey, "non null hash key required");
        if (redisTemplate.getHashKeySerializer() == null && hashKey instanceof byte[]) {
            return (byte[]) hashKey;
        }
        return redisTemplate.getHashKeySerializer().serialize(hashKey);
    }

    /**
     * 序列化 Collection
     * @param collection
     * @return
     */
    public  byte[][] serializerValue(Collection collection) {
        byte[][] rawValues = new byte[collection.size()][];
        int i = 0;
        for (Object value : collection) {
            rawValues[i++] =  redisTemplate.getValueSerializer().serialize(value);
        }
        return rawValues;
    }

    /**
     * 序列化 Collection 集合为Json byte[][]
     * @param collection
     * @return
     * @throws JsonProcessingException
     */
    public  byte[][] serializerJsonValue(Collection collection) throws JsonProcessingException {
        byte[][] rawValues = new byte[collection.size()][];
        int i = 0;
        for (Object value : collection) {
            rawValues[i++] = this.objectMapper.writeValueAsBytes(value);
        }
        return rawValues;
    }

    /**
     * 序列化 Map value 为json byte[]
     * @param map
     * @return
     * @throws Exception
     */
    public  Map<byte[], byte[]> serializerJsonMap(Map map) throws Exception {
        if (map.isEmpty()) {
            throw new Exception("serializerJsonMap : to serializer Map is Empty");
        }
        Map<byte[], byte[]> hashes = new LinkedHashMap<byte[], byte[]>(map.size());
        Set<Map.Entry<Object,Object>> set1 = map.entrySet();
        for (Map.Entry<Object,Object> entry :set1){
            hashes.put(serializerHashKey(entry.getKey()), objectMapper.writeValueAsBytes(entry.getValue()));
        }
        return hashes;
    }

}
